Comment lire des vidéos youtube, seulement avec le son et sans se connecter à la plateforme ?

Mini introduction : Je souhaitais lire mes vidéos de musique épic, sans le son. Je trouve très polluant d'avoir la vidéo, alors que je ne la regarde jamais.

J'ai donc développé un programme en Python & Bash, qui, je vous préviens, n'est pas optimisé et du niveau d'un débutant (je ne suis pas dév).

J'ai laissé mes commentaires, si cela peut vous aider pour d'autres programmes. Pour qu'il fonctionne, vous devez utiliser le logiciel VLC (libre & open source).


Attention, cela ne fonctionne que via VLC, pour les vidéos en live et vous devez au préalable avoir récupéré l'URL, donc il faut se connecter à Youtube.

Voici le programme, en espérant que celui-ci vous serve.


#!/usr/bin/python3.11

#MaJ du 10/07/23
# 10/07/23 => remplacé "Master" par "Speaker" pour la gestion du son & ajout d'une autre commande. J'ai remplacé #!/usr/bin/python3.9 par #!/usr/bin/python3.11 à la suite de la montée de version de Debian 11 à Debian 12.

#But du script
# - Permet d'écouter seulement les vidéos YT en live. Permet de ne pas avoir la vidéo et d'économiser de la bande passante, ce qui est bénéfique pour l'environnement.

#Deroulé du script :
# - Reprend l'ancienne URL ou demande l'ajout de la nouvelle
# - Demande l'ouverture en mode son seulement ou video, cela peut permettre de recuperer l'artiste en cours (par exemple, pour les musiques Epic)
# - Lance le live SANS ou AVEC la vidéo

#Pour les tests du fonctionnement du programme
#print('Hello, world!')


###IMPORT###
# - OS = Commande sur l'OS Linux
# - SubProcess = Pouvoir lancer des commandes en sous-processus permettant de récupérer le résultat, via "subprocess.check_output". Attention à bien utiliser les options, cela permet d'enlever le "b" et "\n" de "b'XXX'\n"
# - Time = Permet de régler le temps, par exemple, ici en ajoutant des pauses
# - Threading = Permet de lancer des doubles tâches. Ici VLC se lance, puis je règle le son de ce dernier. Je ne peux pas faire autrement car VLC est en continue, tant que je ne coupe pas la musique.
import os,subprocess,time,threading


###VARIABLES DU PROGRAMME###

#Réglage des sons.
#PC
son_pc = "16%"
#VLC - Le juste milieux de 65000 est égal à 99% du son. Que le calcul prenne comme base un son à + de 100% ou non.
#Garder l'espace, cela permet de l'ajouter par la suite dans la commande.
son_vlc = " 65000"

#Fichier temporaire VLC
#Chemin
fichier_tmpVLC_chemin = "/tmp/"
#Nom du fichier. Pas besoin d'extension, Linux sait très bien lire les fichiers sans ça, contrairement à WinDaub.
fichier_tmpVLC_nom = "temp_VLC-Python"

#Fichier où est stocké l'URL
#Chemin
fichier_StockageURL_chemin = "/mnt/All_Data/Documents/Tout document/"
#Nom du fichier
fichier_StockageURL_nom = "URL Live YT"


###VARIABLES DES COULEURS###
ColorBrightRed = "\033[1;31;40m"
ColorBrightGreen = "\033[1;32;40m"
ColorBrightBlue = "\033[1;34;40m"
ColorYellow = "\033[1;33;40m"
ColorDarkGrey = "\033[1;30;40m"
FondOrangeTextBlanc = " \033[0;37;43m"

Bold = "\033[1m"
Dim = "\033[2m" #Ajoute de la brillance
Underlined = "\033[4m"
Italique = "\033[3;37;40m"
Blink = "\033[5m" #Permet de clignoter
Reverse = "\033[7m" #Inverse les couleurs
Hidden = "\033[8m" #Cacher le texte

FinChangementPolice = "\033[0m"




###FONCTIONS###
def REGLAGES_SON():
    #Commande permettant de démute le son et de le monter à 20%. => Voir controles : amixer scontrols
    #Ici, garder les 2, cela dépend par quelle priorité il prend le son (rien de sûr, mais ça à le mérite de fonctionner)
    os.system("amixer set Master unmute")
    os.system("amixer set Speaker unmute")
    #os.system("pactl set-sink-mute @DEFAULT_SINK@ toggle")
    #Ici remplacé "Master" par "Speaker". Il y a 2 commandes possibles, anciennes et nouvelles.
    os.system("amixer -D pulse set 'Master' " + son_pc)
    #os.system("amixer sset 'Master' " + son_pc)

    #Réglage de son VLC à 99%, évite qu'il soit trop bas (donc de rien d'entrendre) ou trop haut (donc de saturer le tout)
    #Attente de 5.5sec le temps que le tout charge bien.
    time.sleep(5.5)

    #Création d'un fichier temporaire, n'ayant pas réussi à enregistrer le tout dans une variable.
    os.system("pactl list sink-inputs >  " + fichier_tmpVLC_chemin + fichier_tmpVLC_nom)

    #Commande permettant de récupérer le numéro de ligne, où ce situe la phrase : "icon_name = "vlc""
    #Récupérer du résultat de la commande via le sous-processus.
    #\"vlc\" permet d'échapper les caractères pouvant poser problème dans la commande.
    #Shell=True est obligatoire, sinon la commande ne peux rien récupérer
    #.strip() = permet d'enlever la partie "\n" du résultat "b'XXX'\n"
    resultVLC0 = subprocess.check_output("cat -n " + fichier_tmpVLC_chemin + fichier_tmpVLC_nom + " | grep 'icon_name = \"vlc\"' | awk '{print $1;}'", shell=True).strip()

    #Ici, je récupère le résultat et je le transforme en nombre. "ascii" permet d'enlever "b" qui est la dernière partie de "b'XXX'\n". Ainsi que les guillemets " ' ".
    #Je soustrais le nombre 23, qui correspond au nombre de ligne, pour trouver le résultat au-dessus. Cela ne devrait pas trop changer. Je n'ai pas d'autres solutions, ne savant toujours pas faire de REGEX !
    #Int permet de convertir un nombre de base de données en décimal.
    resultVLCPageX = int(resultVLC0.decode('ascii')) - 23

    #Avec le résultat ci-dessus, sed permet de lire le numéro de ligne. Ensuite j'enlève le surplus de texte "Entrée de la destination #", ce qui correspond à 28 caractères. Le tout nous permet de garder le numéro de processus.
    resultVLC1 = subprocess.check_output("sed -n " + str(resultVLCPageX) + "p " + fichier_tmpVLC_chemin + fichier_tmpVLC_nom + "  | grep 'destination #' | cut -b28- ", shell=True).strip()

    #Commande permettant de règler le son d'une application, selon son numéro de processus, le tout récupéré ci-dessus.
    #Le juste milieux de 65000 est égal à 99% du son. Que le calcul prenne comme base un son à + de 100% ou non.
    #Ici "str(resultVLC1.decode('ascii'))", str permet de convertir la chaine de valeur en charactere, sinon cela ne fonctionne pas.
    os.system("pacmd set-sink-input-volume " + str(resultVLC1.decode('ascii')) + son_vlc)

    #Ensuite je supprime le fichier. Dans tous les cas, les fichiers dans TMP sont supprimés à chaque redémarrage.
    os.system("rm " + fichier_tmpVLC_chemin + fichier_tmpVLC_nom)

    #Pour être sur que la tâche fonctionne toujours
    print(Bold + ColorBrightGreen + Underlined + "SON AUGMENTÉ AUTOMATIQUEMENT" + FinChangementPolice)


def MULTI_TACHES():
    if __name__ == "__main__":
        #Création des tâches
        t1 = threading.Thread(target=LANCEMENT_VLC)
        t2 = threading.Thread(target=REGLAGES_SON)

        #Lancement de la tâche 1
        t1.start()
        #Lancement de la tâche 2
        t2.start()

        #Attend que la tâche 1 soit complétement exécutée
        t1.join()
        #Attend que la tâche 2 soit complétement exécutée
        t2.join()

        #Les 2 tâches sont correctement terminés, donc fin du programme.
        print(Bold + ColorBrightGreen + Underlined + "FIN DU PROGRAMME, MERCI DE L'AVOIR UTILISÉ" + FinChangementPolice)



###DÉBUT DU PROGRAMME###

###AJOUT DE L'URL OU NON###
while True:
    choix = input(ColorBrightRed + "Garder la même URL ? \n" + ColorBrightGreen + "a) OUI\n" + ColorBrightBlue + "b) NON\n" + ColorYellow + Italique + "Choisir " + ColorBrightGreen + "[a]" + ColorYellow +  " ou " + ColorBrightBlue +"[b]" + ColorYellow + ", " + ColorDarkGrey + "[q]" + ColorYellow + " pour Quitter ? : " + FinChangementPolice)
    if choix == "a" or choix == "":
        print(Bold + ColorBrightGreen + "Tu as choissi de garder la même URL.\n\n" + FinChangementPolice)

        #aller chercher URL dans le fichier
        fichier = open(fichier_StockageURL_chemin + fichier_StockageURL_nom, 'r')
        url = fichier.read()
        fichier.close()

        break
    elif choix == "b":
        print(Bold +ColorBrightBlue + "Tu as choissi le changement de l'URL.")
        url = input("Ajoutes l'URL de la video que tu souhaites ecouter via la bande son : ")
        print("Voici la nouvelle URL : " + url + "\n\n")

        #Enregistrement de la nouvelle URL dans le fichier. "w" permet d'autoriser l'écriture.
        fichier = open(fichier_StockageURL_chemin + fichier_StockageURL_nom, 'w')
        fichier.write(url)
        fichier.close()

        break
    elif choix == "q":
        print(Bold + ColorDarkGrey + "Tu as quitté !\n\n" + FinChangementPolice)
        #Demande de quitter, donc arrêter le programme, sinon il passe à la question suivante. Et elle ne pourra être résolue n'ayant pas choisis les variables de cette question.
        quit()
        break





###CHOIX AVEC OU SANS VIDÉO###
#Ici nous avons une boucle infinie, tant qu'elle ne reçoie pas de réponse, elle continue
while True:
    choix = input(ColorBrightRed + "Veux-tu la version SANS ou AVEC la vidéo : \n" + ColorBrightGreen + "a) SANS\n" + ColorBrightBlue + "b) AVEC\n" + ColorYellow + "Choisir  " + ColorBrightGreen + "[a]" + ColorYellow +  " ou " + ColorBrightBlue +"[b]" + ColorYellow + ", " + ColorDarkGrey + "[q]" + ColorYellow + " pour Quitter ? : " + FinChangementPolice)
    if choix == "a" or choix == "":
        print(Bold + ColorBrightGreen + "Tu as choissi SANS." + FinChangementPolice)


        def LANCEMENT_VLC():
            #cvlc = version fenetre. vlc = avec l'ouverture du logiciel, les options ... Je n'ai pas trouvé une bonne option pour afficher une bonne taille de fenetre ! À part l'option plein écran.
            #Je ne sais pas si l'option "best" fonctionne vraiment.
            os.system("cvlc --no-video " + url + " best")


        MULTI_TACHES()


        break
    elif choix == "b":
        print(Bold + ColorBrightBlue + "Tu as choissi AVEC." + FinChangementPolice)

        def LANCEMENT_VLC():
            #cvlc = version fenetre. vlc = avec l'ouverture du logiciel, les options ... Je n'ai pas trouvé une bonne option pour afficher une bonne taille de fenetre ! À part l'option plein écran.
            os.system("vlc " + url + " best")


        MULTI_TACHES()


        break
    elif choix == "q":
        print(Bold + ColorDarkGrey + "Tu as quitté !" + FinChangementPolice)
        break